(function(angular) {
	'use strict';
	angular.module("fs.waf").factory("commonService", ['$rootScope', '$window', '$document', '$filter', '$q', '$parse', 'SYS_PARAMS', 'Constants', 'ajaxServiceFactory', 'dateService', 'modalService', 'storageService', 
	  function($rootScope, $window, $document, $filter, $q, $parse, SYS_PARAMS, Constants, ajaxServiceFactory, dateService, modalService, storageService) {
		var ajaxService = ajaxServiceFactory.buildAjaxService({
			getHolidays : {
				url : 'holidays.do',
				method : 'post'
			},
			getLogo : {
				url : Constants.LOGO_URL,
				method : 'get',
				responseType: 'arraybuffer',
                cache: false,
                transformResponse: function(data, headers) {
                    var blob = null;
                    var contentType = headers('content-type');
                    var fileName = headers('content-disposition');
					if (fileName) {
						fileName = fileName.split(";")[1].trim().split("=")[1];
						fileName = fileName.replace(/"/g, '');
					}
                    if (data) {
                    	blob = new Blob([data], {
                            type: contentType
                        });
                    }
                    var result = {
                    	blob: blob,
                        fileName: fileName
                    };
                    return {
                    	data: result
                    };
                }
			},
			uniqueCheck : {
				url : 'validator/uniqueCheck.do',
				method : 'post'
			},
			lookupCheck : {
				url : 'validator/lookupCheck.do',
				method : 'post'
			},
			getCompanies : {
				url : 'getCompanies.do',
				method : 'post'
			},
			getCompaniesTwo : {
				url : 'getCompaniesTwo.do',
				method : 'post'
			},
			getCompaniesNoAss : {
				url : 'getCompaniesNoAss.do',
				method : 'post'
			},
			getCompaniesNoAssTwo : {
				url : 'getCompaniesNoAssTwo.do',
				method : 'post'
			},
			getRegionAndCountry:{
				url : 'getRegionAndCountry.do',
				method : 'post'
			}
		});
		function buildObjectHashCode(object) {
			var str;
			if (!angular.isObject(object)) {
				return hash('');
			}
			str = toString(object);
			return hash(str || '');

		}
		function toString(object) {
			var t = [], str;
			if (angular.isArray(object)) {
				angular.forEach(object, function(o) {
					str = toString(o);
					if (str) {
						t.push(str);
					}
				});
			} else if (angular.isDate(object) || angular.isNumber(object)) {
				t.push(object.toString());
			} else {
				angular.forEach(object, function(v, k) {
					if (angular.isString(k) && k.indexOf('$') < 0 && k.indexOf('_') < 0 && !(v === null || angular.isUndefined(v) || (angular.isString(v) ? v.trim() == '' : false))) {
						if (angular.isArray(v)) {
							angular.forEach(v, function(o) {
								if (angular.isArray(o)) {
									str = toString(o);
									if (str) {
										t.push(str);
									}
								} else if (angular.isObject(o)) {
									str = toString(o);
									if (str) {
										t.push(str);
									}
								} else {
									str = toString(o);
									if (str) {
										t.push(str);
									}
								}
							});
						} else if (angular.isObject(v)) {
							str = toString(v);
							if (str) {
								t.push(str);
							}
						} else if (angular.isNumber(v)) {
							t.push(v.toString());
						} else {
							t.push(v);
						}
					}
				});
			}
			return t.length > 0 ? t.join(',') : undefined;
		}
		function hash(str) {
			var h = 0, i = 0, n;
			var strlen = str.length;
			if (strlen === 0) {
				return h;
			}
			for (i = 0, n; i < strlen; ++i) {
				n = str.charCodeAt(i);
				h = ((h << 5) - h) + n;
				h = h & h;
			}
			return h >>> 0;
		}
		function isHoliday(date, holidays) {
			if(holidays) {
				var flag = false;
				for(var i=0; i < holidays.length; i++) {
					if(dateService.equalsIgnoreTime(date, holidays[i])) {
						flag = true;
						break;
					}
				}
				return flag;
			} else {
				return false;
			}
		}
		function dateDisabled(dateModel) {
			var date = dateModel.date, mode = dateModel.mode;
			if(mode === 'day') {
				return (date.getDay() === 0 || date.getDay() === 6);
			} else {
				return false;
			}
		}
		//params like {year : calendarYear,ccy : xx,holidaySelectable :xx,countrySelectable : xx}
		function getHolidays(params) {
			var defer = $q.defer();
			ajaxService.getHolidays(params).then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		function getLogo() {
			var defer = $q.defer();
			ajaxService.getLogo({"theme":$rootScope.app.settings.theme}).then(function(response) {
				if(response && response.data && response.data.blob.type.indexOf('image/') >= 0) {
					defer.resolve(URL.createObjectURL(response.data.blob));
				}
			});
			return defer.promise;
		}
		//params like {countryCode : 'CN', cityCode : 'beijing'}
		function uniqueCheck(params) {
			var defer = $q.defer();
			ajaxService.uniqueCheck(params).then(function(response) {
				if(response) {
					defer.resolve(response.data);
				}
			});
			return defer.promise;
		}
		function lookupCheck(params) {
			var defer = $q.defer();
			ajaxService.lookupCheck(params).then(function(response) {
				if(response) {
					defer.resolve(response.data);
				}
			});
			return defer.promise;
		}
		function getCompanies() {
			var defer = $q.defer();
			ajaxService.getCompanies().then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		
		function getCompaniesTwo() {
			var defer = $q.defer();
			ajaxService.getCompaniesTwo().then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		
		function getRegionAndCountry(companyCode) {
			var defer = $q.defer();
			ajaxService.getRegionAndCountry({selectedCompanyCodeTwo : companyCode}).then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		
		/**
		 * get CompanyEntities No Associated company
		 */
		function getCompaniesNoAss() {
			var defer = $q.defer();
			ajaxService.getCompaniesNoAss().then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		
		function getCompaniesNoAssTwo() {
			var defer = $q.defer();
			ajaxService.getCompaniesNoAssTwo().then(function(response) {
				defer.resolve(response ? response.data : []);
			}, function(e) {
				defer.reject(e);
			});
			return defer.promise;
		}
		function isValidOption(arrays, value){
			if(arrays && value){
				for(var i = 0 ;i < arrays.length; i++) {
					if(arrays[i].value === value) {
						return true;
						break;
					}
				}
				return false; 
			}
			return true;
		}
		function buildDownloadService(params, url) {
			if (!url) {
				if ("N" != params.isTemporary) {
					url = 'file/download.do';
				} else {
					url = 'file/download.do';
				}
			} 
			var ajaxService = ajaxServiceFactory.buildAjaxService({
				download : {
	                method: 'POST',
	                url: url,
	                responseType: 'arraybuffer',
	                cache: false,
	                transformResponse: function(data, headers) {
	                    var blob = null;
	                    var contentType = headers('content-type');
	                    var fileName = headers('content-disposition');
						if (fileName) {
							fileName = fileName.split(";")[1].trim().split("=")[1];
							fileName = fileName.replace(/"/g, '');
						}
						if (params.fileName) {
							fileName = params.fileName;
						}
	                    if (data) {
	                    	blob = new Blob([data], {
	                            type: contentType
	                        });
	                    }
	                    var result = {
	                    	blob: blob,
	                        fileName: fileName
	                    };
	                    return {
	                    	data: result
	                    };
	                }
	            }
			});
			return ajaxService;
		}
		function download(params, url) {
			var downloadService, defer = $q.defer();
			try {
				downloadService = buildDownloadService(params, url);
				downloadService.download(params).then(function(response, headers) {
					if (response && response.data) {
						saveAs(response.data.blob, response.data.fileName);
						defer.resolve(response);
					} else {
						defer.reject();
					}
				});
			} catch (e) {
				defer.reject(e);
			}
			return defer.promise;
		}
		function open(params, blob, fileName) {
			if (blob) {
				if (blob.type.indexOf('image/') != -1) {
					openImage(params, blob);
				} else if (blob.type.indexOf('text/') != -1) {
					openText(params, blob);
				} else if (blob.type == 'application/pdf') {
					openPdf(params, blob);
				} else {
					saveAs(blob, fileName);
				}
			}
		}
		function openText(params, blob) {
			var url = URL.createObjectURL(blob);
			params.type = blob.type;
			_openDoc('text.viewer', url, params);
			
		}
		function openPdf(params, blob) {
			var url = URL.createObjectURL(blob);
			params.type = blob.type;
			_openDoc('pdf.viewer', url, params);
		}
		function openImage(params, blob) {
			var url = URL.createObjectURL(blob);
			params.type = blob.type;
			_openDoc('image.viewer', url, params);
		}
		function _openDoc(dialogsModuleId, url, params) {
			modalService.openCustomDialogs({
				'dialogsModule' : dialogsModuleId,
				'size' : params.size || [ 652, 580 ],
				'params' : {
					'url' : url,
					'type' : params.type
				}
			});
		}
		function openDocument(params, url, newWindow, filterParams) {
			var downloadService, defer = $q.defer();
			try {
				if (newWindow) {
					openDocumentInNewWindow(params, url, filterParams)
					defer.resolve();
					return defer.promise;
				}
				downloadService = buildDownloadService(params, url);
				downloadService.download(params).then(function(response, headers) {
					if (response && response.data) {
						open(params, response.data.blob, response.data.fileName);
						defer.resolve(response);
					} else {
						defer.reject();
					}
				}, function(e) {
					defer.reject(e);
				});
			} catch (e) {
				defer.reject(e);
			}
			return defer.promise;
		}
		function openDocumentInNewWindow(params, url, filterParmas) {
			var $form = angular.element("<form action=" + url + " method=\"post\" target=\"_blank\" style=\"display:none\"></form>");
			var csrfToken = Constants.CSRF_TOKEN ? storageService.getItemFromSession(Constants.CSRF_TOKEN) : undefined;
			var transToken = Constants.TRANSACTION_TOKEN ? storageService.getItemFromSession(Constants.TRANSACTION_TOKEN) : undefined;
			params =angular.copy(params);
			if (filterParmas) {
				angular.forEach(filterParmas, function(p) {
					$parse(p).assign(params, null);
				});
			}
			if (csrfToken) {
				params[Constants.CSRF_TOKEN] = csrfToken;
			}
			if (transToken) {
				params[Constants.TRANSACTION_TOKEN] = transToken;
			}
			params = toFlat(params);
			params = formatRequestDate(params);
			angular.forEach(params, function(value, key) {
				var input;
				if (angular.isArray(value)) {
					angular.forEach(value, function(v) {
						input = angular.element("<input type=\"hidden\" name=\"" + key + "\"/>");
						input[0].value = v;
						$form.append(input);
					});
				} else if (value != null && value != undefined) {
					input = angular.element("<input type=\"hidden\" name=\"" + key + "\"/>");
					input[0].value = value;
					$form.append(input);
				}
			});
			angular.element($document[0].querySelector('body')).append($form);
			$document[0].forms[$document[0].forms.length -1].submit();
			$form.remove();
		}
		function toFlat(map) {
			var flatValue = {};
			if (angular.isArray(map)) {
				return flatValue;
			} else if (angular.isObject(map)) {
				Object.keys(map).filter(function(key) {
					var value = map[key];
					if (angular.isArray(value)) {
						angular.forEach(value, function(v, k) {
							if (angular.isObject(v) && !angular.isDate(v)) {
								v = toFlat(v);
								Object.keys(v).filter(function(k2) {
									flatValue[key + '[' + k + '].' + k2] = v[k2];
								});
							} else {
								flatValue[key + '[' + k + ']'] = v;
							}
						});
					} else if (angular.isObject(value) && !angular.isDate(value)) {
						value = toFlat(value);
						Object.keys(value).filter(function(key2) {
							flatValue[key + '.' + key2] = value[key2];
						});
					} else {
						flatValue[key] = value;
					}
				});
			}
			return flatValue;
		}
		function formatRequestDate(requestData) {
			var formatter = storageService.getFormatInfo().longTimestamp;
			function formatDate(requestData) {
				angular.forEach(requestData, function(value, key) {
					if (!requestData.hasOwnProperty(key))
						return;
					if (angular.isDate(value)) {
						requestData[key] = $filter('date')(value, formatter);
					} else if (angular.isObject(value)) {
						formatDate(value);
					}
				});
			}
			formatDate(requestData);
			return requestData;
		}
		function setupDataStatusOptions() {
			return SYS_PARAMS.SETUP_STATUS_OPTIONS;
		}
		/**
		 * var params = {
		 *			'srcTxnType' : ctrl.company.currentDataType,
		 *			'srcTxnRef' : $filter('encode')(ctrl.company.companyCode),
		 *			'isViewPage': true, // true or false, the default value is false.
		 *			'storeTempTableFlag': true or false ,the default is true.
		 *			'entity' :  ctrl.company, //when store to temp Table the entity property is required.
		 *			'relatedDocIdsProp': 'tempDocIds'//the default relatedDocIdsProp value is 'tempDocIds', it is the property in the entity. 
		 *		};
		 */
		function getAttachmentList(params) {
			if(params.storeTempTableFlag == undefined || params.storeTempTableFlag == null) {
				params.storeTempTableFlag = true;
			}
			params.relatedDocIdsProp = params.relatedDocIdsProp || 'tempDocIds';
			modalService.openCustomDialogs({
				'title' : 'title.dialogs.attachmentlistpopup',
				'dialogsModule' : 'cda.popup.documentListController',
				'params' : params,
				'size' : [1100, 500],
				'btnCallback' : {
					'ok' : function(objs) {
					}
				}
			});
		}
		function handleSelectedCompanyCode(companyEntityOptions, companyCode) {
			var selectedCompanyCode = "";
			for (var i = 0; i < companyEntityOptions.length; i++) {
				if ($filter('encode')(companyCode) == $filter('encode')(companyEntityOptions[i].value)) {
					selectedCompanyCode = companyEntityOptions[i].value;
				}
				if (selectedCompanyCode) {
					break;
				} else {
					if (companyEntityOptions[i].subItems && companyEntityOptions[i].subItems.length > 0) {
						selectedCompanyCode = handleSelectedCompanyCode(companyEntityOptions[i].subItems, companyCode);
					}
					if (selectedCompanyCode) break;
				}
			}
			return selectedCompanyCode;
		}
		return {
			hash : buildObjectHashCode,
			isHoliday : isHoliday,
			uniqueCheck : uniqueCheck,
			lookupCheck : lookupCheck,
			getHolidays: getHolidays,
			dateDisabled: dateDisabled,
			getLogo: getLogo,
			setupDataStatusOptions : setupDataStatusOptions,
			isValidOption : isValidOption,
			download : download,
			openDocument : openDocument,
			getAttachmentList : getAttachmentList,
			getCompanies : getCompanies,
			getCompaniesNoAss : getCompaniesNoAss,
			getCompaniesNoAssTwo : getCompaniesNoAssTwo,
			getCompaniesTwo : getCompaniesTwo,
			getRegionAndCountry : getRegionAndCountry,
			handleSelectedCompanyCode : handleSelectedCompanyCode
		};
	}]);
})(angular);
